//
// Created by francklinson on 2021/10/21 AT 15:56.
//
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <algorithm>
#include <functional>
#include <climits>
#include <string>

using namespace std;

class Solution {
public:
    vector<int> productExceptSelf(vector<int> &nums) {
        // 构造两个额外的数组 分别存储当前位置左右两侧的乘积  最终的结果为L[i]*R[i]
        int n = nums.size();
        vector<int> L(n);
        vector<int> R(n);
        L[0] = 1;
        for (int i = 1; i < n; ++i) {
            L[i] = L[i - 1] * nums[i - 1];
        }
        R[n - 1] = 1;
        for (int i = n - 2; i >= 0; --i) {
            R[i] = R[i + 1] * nums[i + 1];
        }
        vector<int> ans(n);
        for (int i = 0; i < n; ++i) {
            ans[i] = L[i] * R[i];
        }
        return ans;
    }

    vector<int> productExceptSelf2(vector<int> &nums) {
        // 不再额外构造L R 数组 而是借用结果数组
        int length = nums.size();
        vector<int> answer(length);

        // answer[i] 表示索引 i 左侧所有元素的乘积
        // 因为索引为 '0' 的元素左侧没有元素， 所以 answer[0] = 1
        answer[0] = 1;
        for (int i = 1; i < length; i++) {
            answer[i] = nums[i - 1] * answer[i - 1];
        }

        // R 为右侧所有元素的乘积
        // 刚开始右边没有元素，所以 R = 1
        int R = 1;
        for (int i = length - 1; i >= 0; i--) {
            // 对于索引 i，左边的乘积为 answer[i]，右边的乘积为 R
            answer[i] = answer[i] * R;
            // R 需要包含右边所有的乘积，所以计算下一个结果时需要将当前值乘到 R 上
            R *= nums[i]; // 动态更新右侧的累乘值
        }
        return answer;
    }
};

int main() {
    vector<int> nums{1, 2, 3, 4};
    Solution solution;
    vector<int> ans = solution.productExceptSelf(nums);
    for (auto &x: ans) cout << x << endl;
    return 0;
}

